#include <iostream>
#include "../includes/need-a-name.hh"
#include "../includes/project-base.hh"
#include "../includes/subproject-base.hh"
#include "../includes/equation-base.hh"
#include "../includes/init-base.hh"
#include "../includes/boundary-base.hh"

#include "../equations/includes/mhd.hh"
#include "includes/project_mhd_1D_YASP.hh"
#include "../initcollecter/includes/initcollecter-mhd.hh"


namespace MHDTest{
class LFTest : public SubprojectBase{
public:
  void set_subproject_signature(){
    subproject_signature="lfTest";
  }
  void assign_equation(){
    std::cout<<"assign MHD equation"<<std::endl;
    equation=new MHD();
  }
  void assign_initialcondition(){
    init=new InitCollecterMHD();
  }
  void assign_boundarycondition(){
    boundary=new BoundaryBase();
  }
  void set_unique_parameters(){
    std::cout<<"set unique parameters"<<std::endl;
    setting::spacediscrete = setting::lf;
    memory::dgflag=0;
  }
  void dataanalysis(){
  }
};

class dgLFTest : public SubprojectBase{
public:
  void set_subproject_signature(){
    subproject_signature="dglfTest";
  }
  void assign_equation(){
    std::cout<<"assign MHD equation"<<std::endl;
    equation=new MHD();
  }
  void assign_initialcondition(){
    init=new InitCollecterMHD();
  }
  void assign_boundarycondition(){
    boundary=new BoundaryBase();
  }
  void set_unique_parameters(){
    std::cout<<"set unique parameters"<<std::endl;
    setting::spacediscrete = setting::lf;
    memory::dgflag=1;
    memory::dgorder=3;
    memory::intergnumber=500;    
  }
  void dataanalysis(){
  }
};

class dgrkLFTest : public SubprojectBase{
public:
  void set_subproject_signature(){
    subproject_signature="dgrklfTest";
  }
  void assign_equation(){
    std::cout<<"assign MHD equation"<<std::endl;
    equation=new MHD();
  }
  void assign_initialcondition(){
    init=new InitCollecterMHD();
  }
  void assign_boundarycondition(){
    boundary=new BoundaryBase();
  }
  void set_unique_parameters(){
    std::cout<<"set unique parameters"<<std::endl;
    setting::spacediscrete = setting::lf;
    memory::dgflag=1;
    memory::dgorder=3;
    memory::intergnumber=500;    
  }
  void dataanalysis(){
  }
};
  
class TVDLFTest : public SubprojectBase{
public:
  void set_subproject_signature(){
    subproject_signature="tvdlfTest";
  }
  void assign_equation(){
    std::cout<<"assign euler equation"<<std::endl;
    equation=new MHD();
  }
  void assign_initialcondition(){
    init=new InitCollecterMHD();
  }
  void assign_boundarycondition(){
    boundary=new BoundaryBase();
  }
  void set_unique_parameters(){
    std::cout<<"set unique parameters"<<std::endl;
    setting::spacediscrete = setting::tvdlf;
  }
  void dataanalysis(){
  }
};


class rk2TVDLFTest : public SubprojectBase{
public:
  void set_subproject_signature(){
    subproject_signature="rk2TVDLFTest";
  }
  void assign_equation(){
    equation=new MHD();
  }
  void assign_initialcondition(){
    init=new InitCollecterMHD();
  }
  void assign_boundarycondition(){
    boundary=new BoundaryBase();
  }
  void set_unique_parameters(){
    std::cout<<"set unique parameters"<<std::endl;
    memory::dgflag=0;
    memory::dgorder=0;        
    setting::timeadvance=setting::rk2;
    setting::spacediscrete = setting::tvdlf;
    setting::limiter = setting::minmod;    
  }
  void dataanalysis(){
  }
};
class rk3TVDLFTest : public SubprojectBase{
public:
  void set_subproject_signature(){
    subproject_signature="rk3TVDLFTest";
  }
  void assign_equation(){
    equation=new MHD();
  }
  void assign_initialcondition(){
    init=new InitCollecterMHD();
  }
  void assign_boundarycondition(){
    boundary=new BoundaryBase();
  }
  void set_unique_parameters(){
    std::cout<<"set unique parameters"<<std::endl;
    memory::dgflag=0;
    memory::dgorder=0;        
    setting::timeadvance=setting::rk3;
    setting::spacediscrete = setting::tvdlf;
    setting::limiter = setting::minmod;    
  }
  void dataanalysis(){
  }
};





}


//-----------------------------------------
Project_MHD_1D_YASP::Project_MHD_1D_YASP(){ 
}
Project_MHD_1D_YASP::~Project_MHD_1D_YASP(){
}
void Project_MHD_1D_YASP::set_project_signature(){
  project_signature="MHD_1D_YASP";
}

void Project_MHD_1D_YASP::set_common_parameters(int subproj){
  // Grid and dimension need to be assigned in driver-file.cc and setting.hh
  // Grid: #define YASP
  // dimension: const int dimension=1
  setting::timeadvance=setting::euler;
  setting::boundary=setting::constant;
  gridsetting::lower[0]=0.0;
  gridsetting::upper[0]=1.0;
  gridsetting::element[0]=800;
  timerule::start=0.0;
  timerule::end=0.3;
  timerule::dt=1.0E-100;
  timerule::current=0.0;
  timerule::counter=0.0;
  timerule::cfl=0.8;
  memory::dgorder=0;
  // equation parameter
  // TODO: set init parameter by equation parameter
  get_subproject(subproj)->equation->set_parameter("gamma",5.0/3.0);
  // init parameter
  get_subproject(subproj)->init->set_parameter("gamma",5.0/3.0);
  get_subproject(subproj)->init->set_parameter("sod_shocktube_leve",1.0);
  get_subproject(subproj)->init->set_parameter("sod_shocktube_stone",0.0);
  get_subproject(subproj)->init->set_parameter("briowu",0.0);  
  // boundary setting
  for(int tmpp=0; tmpp<memory::phynumber; tmpp++)
    for(int tmpd=0; tmpd<gridsetting::dimension; tmpd++){
      get_subproject(subproj)->boundary->left[tmpp][tmpd]="const";
      get_subproject(subproj)->boundary->left[tmpp][tmpd]="const";      
    }
}

void Project_MHD_1D_YASP::load_subprojects(){
  // add_subproject(new MHDTest::dgLFTest());
  // add_subproject(new MHDTest::dgrkLFTest());    
  add_subproject(new MHDTest::LFTest());
  // // add_subproject(new MHDTest::LWTest());
  add_subproject(new MHDTest::rk2TVDLFTest());
  // add_subproject(new MHDTest::rk3TVDLFTest());
  add_subproject(new MHDTest::TVDLFTest());
};
